//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_member_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/org_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/notices/notices_user"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_member_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectMemberApiImpl) AddFromOrg(ctx context.Context, req *project_member_api.AddFromOrgRequest) (*project_member_api.AddFromOrgResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_member_api.AddFromOrgResponse{
			Code:   project_member_api.AddFromOrgResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_member_api.AddFromOrgResponse{
			Code:   project_member_api.AddFromOrgResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_member_api.AddFromOrgResponse{
			Code:   project_member_api.AddFromOrgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_member_api.AddFromOrgResponse{
			Code:   project_member_api.AddFromOrgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(roleItem.BasicInfo.Admin || projectItem.OwnerUserId == sessionItem.UserId) {
		return &project_member_api.AddFromOrgResponse{
			Code:   project_member_api.AddFromOrgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查项目中是否存在成员
	exist, err := project_dao.MemberInfoDao.Exist(ctx, req.ProjectId, req.MemberUserId)
	if err != nil {
		return nil, err
	}
	if exist {
		return &project_member_api.AddFromOrgResponse{
			Code: project_member_api.AddFromOrgResponse_CODE_OK,
		}, nil
	}

	//检查组织是否存在
	exist, err = org_dao.OrgInfoDao.Exist(ctx, req.OrgId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_member_api.AddFromOrgResponse{
			Code:   project_member_api.AddFromOrgResponse_CODE_NO_ORG,
			ErrMsg: "组织不存在",
		}, nil
	}
	//检查是否是组织成员
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_member_api.AddFromOrgResponse{
			Code:   project_member_api.AddFromOrgResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查组织中是否存在用户
	exist, err = org_dao.MemberDao.Exist(ctx, req.OrgId, req.MemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_member_api.AddFromOrgResponse{
			Code:   project_member_api.AddFromOrgResponse_CODE_NO_MEMBER,
			ErrMsg: "组织成员不存在",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6
	noticeFromId := user_dao.GetIdForAddToProjectFromOrgData(req.ProjectId)

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_dao.AckJoinDao.Remove(sessCtx, req.ProjectId, req.MemberUserId)
		if err != nil {
			return nil, err
		}
		err = project_dao.AckJoinDao.Insert(sessCtx, &project_dao.AckJoinDbItem{
			ProjectId:    req.ProjectId,
			MemberUserId: req.MemberUserId,
			TimeStamp:    nowTime,
		})
		if err != nil {
			return nil, err
		}
		err = user_dao.UserNoticeDao.Remove(sessCtx, req.MemberUserId, noticeFromId)
		if err != nil {
			return nil, err
		}
		err = user_dao.UserNoticeDao.Insert(sessCtx, &user_dao.UserNoticeInfoDbItem{
			UserId:       req.MemberUserId,
			NoticeFromId: noticeFromId,
			TimeStamp:    nowTime,
			HasRead:      false,
			SendUserId:   sessionItem.UserId,
			AddToProjectFromOrgData: &user_dao.AddToProjectFromOrgDataDbItem{
				ProjectId: req.ProjectId,
				OrgId:     req.OrgId,
			},
		})
		if err != nil {
			return nil, err
		}
		return &project_member_api.AddFromOrgResponse{
			Code: project_member_api.AddFromOrgResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToUser(context.Background(), req.MemberUserId, &notices_user.UserNewNoticeNotice{
		UserId: req.MemberUserId,
	})
	return ret.(*project_member_api.AddFromOrgResponse), nil
}

func (apiImpl *ProjectMemberApiImpl) AckJoin(ctx context.Context, req *project_member_api.AckJoinRequest) (*project_member_api.AckJoinResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_member_api.AckJoinResponse{
			Code:   project_member_api.AckJoinResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := project_dao.MemberInfoDao.Exist(ctx, req.ProjectId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if exist {
		return &project_member_api.AckJoinResponse{
			Code: project_member_api.AckJoinResponse_CODE_OK,
		}, nil
	}
	projectItem, err := project_dao.ProjectInfoDao.Get(ctx, req.ProjectId)
	if err != nil {
		return &project_member_api.AckJoinResponse{
			Code:   project_member_api.AckJoinResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	}
	if projectItem.Closed {
		return &project_member_api.AckJoinResponse{
			Code:   project_member_api.AckJoinResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err = project_dao.AckJoinDao.Exist(ctx, req.ProjectId, sessionItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_member_api.AckJoinResponse{
			Code:   project_member_api.AckJoinResponse_CODE_NO_INVITE,
			ErrMsg: "未邀请加入项目",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = api_common.AddMember(sessCtx, nowTime, projectItem, sessionItem.UserId, "")
		if err != nil {
			return nil, err
		}
		noticeFromId := user_dao.GetIdForAddToProjectFromOrgData(req.ProjectId)
		err = user_dao.UserNoticeDao.Remove(sessCtx, sessionItem.UserId, noticeFromId)
		if err != nil {
			return nil, err
		}
		return &project_member_api.AckJoinResponse{
			Code: project_member_api.AckJoinResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*project_member_api.AckJoinResponse), nil
}
